﻿using System;
using System.Net;
using System.Web;
using System.Xml;

namespace RemoteTestRunner.UnitTesting
{
    #region Enumerated Types

    /// <summary>
    /// Specifies a connection string setting.
    /// </summary>
    public enum ConnectionStringSetting
    {
        /// <summary>
        /// The application name.
        /// </summary>
        ApplicationName,

        /// <summary>
        /// The connection timeout value.
        /// </summary>
        ConnectionTimeout,

        /// <summary>
        /// The current language.
        /// </summary>
        CurrentLanguage,

        /// <summary>
        /// The database name.
        /// </summary>
        Database,

        /// <summary>
        /// The data source.
        /// </summary>
        DataSource,

        /// <summary>
        /// The encryption setting.
        /// </summary>
        Encrypt,

        /// <summary>
        /// The Integrated Security (SSPI) setting.
        /// </summary>
        IntegratedSecurity,

        /// <summary>
        /// The server instance.
        /// </summary>
        Instance,

        /// <summary>
        /// The packet size.
        /// </summary>
        PacketSize,

        /// <summary>
        /// The database password.
        /// </summary>
        Password,

        /// <summary>
        /// The persist security information setting.
        /// </summary>
        PersistSecurityInfo,

        /// <summary>
        /// The database server.
        /// </summary>
        Server,

        /// <summary>
        /// The database server and instance combined.
        /// </summary>
        ServerAndInstance,

        /// <summary>
        /// The database logon ID.
        /// </summary>
        UserId,

        /// <summary>
        /// The workstation ID.
        /// </summary>
        WorkstationId
    }

    #endregion

    /// <summary>
    /// This class provides various helper methods for the <see cref="MultiAssertTestClassHelper"/> class.
    /// </summary>
    public class Helper
    {
        /// <summary>
        /// Returns a specific setting within a SQL Server connection string.
        /// </summary>
        /// <param name="connectionString">The connection string to parse.</param>
        /// <param name="setting">The name of the setting to return.</param>
        /// <returns>Returns a String value for the specified connection string setting.  An 
        /// empty string is returned if the setting is not present.</returns>
        public static string GetConnectionStringSetting(string connectionString, ConnectionStringSetting setting)
        {
            string[] settings;
            string[] settingsKeys;
            var csSetting = string.Empty;
            var settingKey = string.Empty;
            int position;

            if (connectionString != null)
            {
                switch (setting)
                {
                    case ConnectionStringSetting.ApplicationName:
                        settingKey = "application name";
                        break;
                    case ConnectionStringSetting.ConnectionTimeout:
                        settingKey = "connect timeout;connection timeout";
                        break;
                    case ConnectionStringSetting.CurrentLanguage:
                        settingKey = "current language";
                        break;
                    case ConnectionStringSetting.Database:
                        settingKey = "initial catalog;database";
                        break;
                    case ConnectionStringSetting.Encrypt:
                        settingKey = "encrypt";
                        break;
                    case ConnectionStringSetting.IntegratedSecurity:
                        settingKey = "integrated security;trusted_connection";
                        break;
                    case ConnectionStringSetting.PacketSize:
                        settingKey = "packet size";
                        break;
                    case ConnectionStringSetting.Password:
                        settingKey = "password;pwd";
                        break;
                    case ConnectionStringSetting.PersistSecurityInfo:
                        settingKey = "persist security info";
                        break;
                    case ConnectionStringSetting.DataSource:
                    case ConnectionStringSetting.Server:
                    case ConnectionStringSetting.Instance:
                    case ConnectionStringSetting.ServerAndInstance:
                        settingKey = "data source;server;address;network address";
                        break;
                    case ConnectionStringSetting.UserId:
                        settingKey = "user id";
                        break;
                    case ConnectionStringSetting.WorkstationId:
                        settingKey = "workstation id";
                        break;
                }

                settings = connectionString.Split(';');

                for (var index = 0; index <= (settings.Length - 1); index++)
                {
                    settingsKeys = settingKey.Split(';');

                    for (var keyIndex = 0; keyIndex <= (settingsKeys.Length - 1); keyIndex++)
                    {
                        if (settings[index].Trim().ToLower().IndexOf(settingsKeys[keyIndex]) >= 0)
                        {
                            csSetting = settings[index].Substring(settings[index].IndexOf("=") + 1);

                            break;
                        }
                    }

                    if (csSetting.Length > 0)
                    {
                        break;
                    }
                }
            }

            if (setting == ConnectionStringSetting.Server)
            {
                // Remove the instance name from the server/instance setting if one exists
                position = csSetting.IndexOf("\\");

                if (position > 0)
                {
                    csSetting = csSetting.Substring(0, position);
                }
            }
            else if (setting == ConnectionStringSetting.Instance)
            {
                // Remove the server name from the server/instance setting if one exists
                position = csSetting.IndexOf("\\");

                if ((position > 0) && ((position + 1) < csSetting.Length))
                {
                    csSetting = csSetting.Substring(position + 1);
                }
            }

            return csSetting;
        }

        /// <summary>
        /// Gets the specified attribute value from the attribute collection.
        /// </summary>
        /// <param name="attributes">The collection of attributes to search.</param>
        /// <param name="name">The name of the attribute value to retrieve.</param>
        /// <returns>If found, the value of the specified attribute; otherwise, and empty string
        /// is returned.</returns>
        public static string GetAttributeValue(XmlAttributeCollection attributes, string name)
        {
            var value = string.Empty;

            foreach (XmlAttribute attribute in attributes)
            {
                if (string.Equals(attribute.Name, name, StringComparison.InvariantCultureIgnoreCase))
                {
                    value = attribute.Value;

                    break;
                }
            }

            return value;
        }

        /// <summary>
        /// Downloads a file from a specified URI to a local or UNC path.
        /// </summary>
        /// <param name="requestUriString">The URI of the file to be downloaded.</param>
        /// <param name="desinationPath">The desination path.</param>
        /// <returns><c>true</c> if the download is successful; otherwise, <c>false</c>.</returns>
        /// <remarks>The caller must have permission to both the source and destination.</remarks>
        public static bool DownloadFile(string requestUriString, string desinationPath)
        {
            var success = true;

            try
            {
                var client = new WebClient { UseDefaultCredentials = true };

                client.DownloadFile(requestUriString, HttpUtility.UrlDecode(desinationPath));
            }
            catch
            {
                success = false;
            }

            return success;
        }
    }
}